package com.poizon.infrastructure.idem.core.util.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.poizon.infrastructure.idem.core.util.IRepeatedSubmitUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

import static com.poizon.infrastructure.idem.core.domain.value.config.IdemConstants.*;
import static com.poizon.infrastructure.idem.core.util.impl.AbstractIdemUtil.Check.preParamCheck;

@Slf4j
@AllArgsConstructor
public abstract class AbstractRepeatedSubmitUtil implements IRepeatedSubmitUtil {

    protected static class Get {
        public static String getIdemKey(String operationKey) {
            String idemKey = StrUtil.format("{}:{}", REPEATED_SUBMIT_KEY_PREFIX, operationKey);
            return idemKey;
        }
    }

    protected static class Check {
        /**
         * 预检查/防重提交参数
         */
        protected static void preParamCheck(String operationKey, Long expireTime, Runnable serviceRunnable, Runnable repeatedRunnable, TimeUnit timeUnit) {
            Assert.notBlank(operationKey, "operationKey不能为空");
            Assert.notNull(expireTime, "expireTime不能为空");
            Assert.isTrue(expireTime > 0, "expireTime必须大于0");
            Assert.notNull(serviceRunnable, "serviceRunnable不能为空");
            Assert.notNull(timeUnit, "timeUnit不能为空");
        }
    }

    /**
     * 模版方法/执行防重提交
     */
    protected abstract void executeRepeatedSubmitImpl(String operationKey, Long expireTime, Runnable serviceRunnable, Runnable repeatedRunnable, TimeUnit timeUnit);

    @Override
    public void executeRepeatedSubmit(String operationKey, Long expireTime, Runnable serviceRunnable, Runnable repeatedRunnable, TimeUnit timeUnit) {
        preParamCheck(operationKey, expireTime, serviceRunnable, repeatedRunnable, timeUnit);
        executeRepeatedSubmitImpl(operationKey, expireTime, serviceRunnable, repeatedRunnable, timeUnit);
    }

    @Override
    public void executeRepeatedSubmit(String operationKey) {
        executeRepeatedSubmit(operationKey, DEFAULT_REPEATED_SUBMIT_KEY_EXPIRE_TIME);
    }

    @Override
    public void executeRepeatedSubmit(String operationKey, Long defaultExpireTime) {
        executeRepeatedSubmit(operationKey, defaultExpireTime, DEFAULT_SERVICE_RUNNABLE);
    }

    @Override
    public void executeRepeatedSubmit(String operationKey, Long defaultExpireTime, Runnable defaultServiceRunnable) {
        executeRepeatedSubmit(operationKey, defaultExpireTime, defaultServiceRunnable, DEFAULT_REPEATED_RUNNABLE);
    }

    @Override
    public void executeRepeatedSubmit(String operationKey, Long defaultExpireTime, Runnable
            defaultServiceRunnable, Runnable defaultRepeatedRunnable) {
        executeRepeatedSubmit(operationKey, defaultExpireTime, defaultServiceRunnable, defaultRepeatedRunnable, DEFAULT_REPEATED_SUBMIT_KEY_TIME_UNIT);
    }

    @Override
    public void executeRepeatedSubmit(String operationKey, Long defaultExpireTime, Runnable
            defaultServiceRunnable, TimeUnit timeUnit) {
        executeRepeatedSubmit(operationKey, defaultExpireTime, defaultServiceRunnable, DEFAULT_REPEATED_RUNNABLE, timeUnit);
    }
}
